/**
 * Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springblade.modules.restaurant.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.core.util.StrUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.secure.utils.SecureUtil;
import org.springblade.core.tool.utils.ObjectUtil;
import org.springblade.modules.restaurant.entity.Area;
import org.springblade.modules.restaurant.entity.Task;
import org.springblade.modules.restaurant.entity.TaskRecord;
import org.springblade.modules.restaurant.entity.TaskTemplate;
import org.springblade.modules.restaurant.enums.TaskCycleEnums;
import org.springblade.modules.restaurant.enums.TaskRecordStatusEnums;
import org.springblade.modules.restaurant.enums.TaskStatusEnums;
import org.springblade.modules.restaurant.mapper.TaskMapper;
import org.springblade.modules.restaurant.service.IAreaService;
import org.springblade.modules.restaurant.service.ITaskRecordService;
import org.springblade.modules.restaurant.service.ITaskService;
import org.springblade.modules.restaurant.service.ITaskTemplateService;
import org.springblade.modules.restaurant.vo.TaskIssueVO;
import org.springblade.modules.restaurant.vo.TaskVO;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 任务表 服务实现类
 *
 * @author Blade
 * @since 2025-01-21
 */
@Slf4j
@Service
@AllArgsConstructor
public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implements ITaskService {

	private final IUserService userService;
	private final IAreaService areaService;
	private final ITaskRecordService taskRecordService;
	private final ITaskTemplateService taskTemplateService;

	@Override
	public IPage<TaskVO> selectTaskPage(IPage<TaskVO> page, TaskVO task) {
		return page.setRecords(baseMapper.selectTaskPage(page, task));
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean taskIssue(TaskIssueVO taskIssueVO) {
		Long taskIds = taskIssueVO.getId();
		List<Task> taskList = listByIds(Collections.singleton(taskIds));
		return createTaskRecord(taskList, taskIssueVO);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void genTaskRecord() {
		// 根据任务周期  任务状态 生成任务记录
		List<TaskTemplate> list = taskTemplateService.list(Wrappers.<TaskTemplate>lambdaQuery()
			.eq(TaskTemplate::getStatus, TaskStatusEnums.START.getStatus()));

		if (list == null || list.isEmpty()) {
			log.info("没有任务模板");
			return;
		}
		createTasks(list);
	}

	@Transactional(rollbackFor = Exception.class)
	public void createTasks(List<TaskTemplate> list) {
		List<TaskTemplate> upadteList = new ArrayList<>();
		List<Task> tasks = new ArrayList<>();
		for (TaskTemplate taskTemplate : list) {
			// 下发规则
			boolean isIssue = issueRule(taskTemplate);

			if (isIssue) {
				Task task = new Task();
				task.setTaskTime(DateUtil.today());
				task.setLastTime(taskTemplate.getLastTime());
				task.setAreaIds(taskTemplate.getAreaId());
				task.setTaskName(taskTemplate.getTaskName());
				task.setAnnouncements(taskTemplate.getAnnouncements());
				task.setSampleGraph(taskTemplate.getSampleGraph());
				task.setType(0);
				task.setCycle(taskTemplate.getCycle());
				task.setTimeType(taskTemplate.getTimeType());
				task.setUserIds(taskTemplate.getUserId());
				task.setDeadline(taskTemplate.getDeadline());
				task.setInspectDeadline(taskTemplate.getInspectDeadline());

				task.setTenantId(taskTemplate.getTenantId());
				task.setStatus(TaskStatusEnums.START.getStatus());
				task.setCreateUser(task.getCreateUser());
				task.setCreateDept(task.getCreateDept());
				tasks.add(task);

				DateTime now = DateUtil.date();
				TaskTemplate updateTaskTemplate = BeanUtil.copyProperties(taskTemplate, TaskTemplate.class);
				updateTaskTemplate.setLastTime(now);
				upadteList.add(updateTaskTemplate);
			}
		}
		saveBatch(tasks);
		taskTemplateService.updateBatchById(upadteList);
	}

	private boolean issueRule(TaskTemplate taskTemplate) {
		Long id = taskTemplate.getId();
		Integer cycle = taskTemplate.getCycle();
		String timeRule = taskTemplate.getTimeRule();
		Integer timeValue = taskTemplate.getTimeValue();
		Date lastTime = taskTemplate.getLastTime();
		DateTime now = DateUtil.date();
		String time = covertDateTime(now, cycle, timeRule, timeValue);

		if (Objects.isNull(taskTemplate.getUserId())) {
			log.info("不允许下发===> 用户ID为空,任务模板ID:{}", id);
			return false;
		}

		if (StrUtil.isBlank(time)) {
			log.info("不允许下发===> 时间规则为空,任务模板ID:{},周期：{}，规则：{} {}", id, cycle, timeRule, timeValue);
			return false;
		}
		DateTime date = DateUtil.parse(time);
		if (now.isBefore(date)) {
			log.info("不允许下发===> 规则时间在当前时间之前，不予下发,任务模板ID:{},规则时间：{}，当前时间：{}", id, date, now);
			return false;
		}
		if (ObjectUtil.isEmpty(lastTime)) {
			log.info("允许下发===> 最近一次下发时间为空，允许下发,任务模板ID:{},当前时间：{}", id, now);
			return true;
		}
		if (DateUtil.isSameDay(now, lastTime)) {
			log.info("不允许下发===> 最近一次下发时间与当前时间相同，不允许下发,任务模板ID:{},最近一次下发时间：{}，当前时间：{}", id, lastTime, now);
			return false;
		}
		log.info("允许下发===> 任务模板ID:{},最近一次下发时间：{}，当前时间：{},规则时间：{}", id, lastTime, now, date);
		return true;
	}

	/**
	 * 根据规则完善时间格式 时间格式：yyyy-MM-dd HH:mm:ss
	 *
	 * @param now       当前时间
	 * @param cycle     任务周期
	 * @param timeRule  时间规则 HH:mm
	 * @param timeValue 时间值
	 * @return
	 */
	private String covertDateTime(DateTime now, Integer cycle, String timeRule, Integer timeValue) {
		if (ObjectUtil.isEmpty(timeRule)) {
			log.error("时间规则为空,请先配置时间规则：{}", timeRule);
			return null;
		}

		String time = DateUtil.formatDate(now) + " " + timeRule + ":00";

		// 任务周期 1 每天 2 每周 3 每月
		if (Objects.equals(TaskCycleEnums.EVERY_DAY.getCode(), cycle)) {
			// 日
			return time;
		}
		if (Objects.equals(TaskCycleEnums.EVERY_WEEK.getCode(), cycle)) {
			// 周
			int week = DateUtil.dayOfWeek(now);
			return week == timeValue ? time : null;
		}
		if (Objects.equals(TaskCycleEnums.EVERY_MONTH.getCode(), cycle)) {
			// 月
			int day = DateUtil.dayOfMonth(now);
			return day == timeValue ? time : null;
		}
		return null;
	}

	@Transactional(rollbackFor = Exception.class)
	public boolean createTaskRecord(List<Task> taskList, TaskIssueVO taskIssueVO) {
		List<TaskRecord> taskRecordList = new ArrayList<>();
		String taskTime = DateUtil.formatDate(DateUtil.date());

		for (Task task : taskList) {
			task.setLastTime(DateUtil.date());
			// 1. 获取负责人
			String userIds = StrUtil.isBlank(taskIssueVO.getUserIds()) ? task.getUserIds() : taskIssueVO.getUserIds();
			if (StrUtil.isBlank(userIds)) {
				continue;
			}
			TaskRecord item = new TaskRecord();

			item.setTaskId(task.getId());
			item.setTaskTime(taskTime);
			item.setTaskName(task.getTaskName());
			item.setUserId(Long.valueOf(userIds));
			item.setSampleGraph(task.getSampleGraph());
			item.setAnnouncements(task.getAnnouncements());
			item.setType(task.getType());
			item.setTenantId(task.getTenantId());

			item.setTimeType(taskIssueVO.getTimeType());
			String deadline = taskIssueVO.getDeadline();
			item.setDeadline(deadline);

			// 检查人即下发人
			item.setInspectorId(SecureUtil.getUserId());
			item.setInspectorName(SecureUtil.getUserName());

			// 获取用户
			User user = userService.getById(Long.valueOf(userIds));
			if (user != null) {
				item.setUserId(user.getId());
				item.setUserName(user.getRealName());
			} else {
				log.error("任务负责人不存在,任务ID:{},负责人ID:{}", task.getId(), userIds);
				continue;
			}

			String areaIds = task.getAreaIds();
			if (StrUtil.isNotBlank(areaIds)) {
				Area area = areaService.getById(Long.valueOf(areaIds));
				if (area == null) {
					log.error("任务区域不存在,任务ID:{},区域ID:{}", task.getId(), areaIds);
				} else {
					item.setAreaId(Long.valueOf(areaIds));
					item.setAreaName(area.getAreaName());
				}
			}

			item.setStatus(TaskRecordStatusEnums.WAIT_SUBMIT.getCode());
			taskRecordList.add(item);
		}
		updateBatchById(taskList);
		return taskRecordService.saveBatch(taskRecordList);
	}

}
